package cn.edu.thu.tsqualitylite.controller;

import cn.edu.thu.tsquality.core.common.datasource.CsvDataSource;
import cn.edu.thu.tsquality.core.common.datasource.IDataSource;
import cn.edu.thu.tsquality.core.common.util.ArgumentsHelper;
import cn.edu.thu.tsqualitylite.common.constant.Algorithms;
import cn.edu.thu.tsqualitylite.common.constant.Constants;
import cn.edu.thu.tsqualitylite.common.util.ServerTable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by wangyihan  on 2018/4/22 下午5:34.
 * E-mail address is yihanwang22@163.com.
 * Copyright © 2017 wangyihan. All Rights Reserved.
 *
 * @author wangyihan
 */
@Controller
public class ExampleController {

  @RequestMapping(value = "/api/example/algorithms", method = RequestMethod.POST)
  @ResponseBody
  public ServerTable runAlgorithm(
      @RequestBody Map<String, Object> params
  ) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {
    String algorithmName = params.get("algorithmName").toString();
    String inputFilename = params.get("inputFilename").toString();
    // TODO: judge window absolute path
    if (!inputFilename.startsWith("/") && inputFilename.charAt(1) != ':') {
      inputFilename = Constants.DATA_PATH + inputFilename;
    }
    String outputFilename = params.get("outputFilename").toString();
    if (!outputFilename.startsWith("/") && outputFilename.charAt(1) != ':') {
      outputFilename = Constants.RESULT_PATH + outputFilename;
    }
    String parameters = params.get("parameters").toString();
    Class algorithm = Algorithms.getAlgorithm(algorithmName);
    Method method = algorithm.getMethod("main", String[].class);
    String[] args = new String[]{inputFilename, outputFilename, parameters};
    method.invoke(null, (Object) args);
    IDataSource dataSource = new CsvDataSource(outputFilename);
    return new ServerTable(dataSource.read());
  }

  @RequestMapping(value = "/api/example/multiput-algorithms", method = RequestMethod.POST)
  @ResponseBody
  public List<ServerTable> runMultiputAlgorithm(
      @RequestBody Map<String, Object> params
  ) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    String algorithmName = params.get("algorithmName").toString();
    String inputFilenames = params.get("inputFilenames").toString();
    String outputFilenames = params.get("outputFilenames").toString();
    String parameters = params.get("parameters").toString();

    String[] inputFileArray = ArgumentsHelper.getValues(inputFilenames);
    for (int i = 0; i < inputFileArray.length; ++i) {
      if (!inputFileArray[i].startsWith("/") && inputFileArray[i].charAt(1) != ':') {
        inputFileArray[i] = Constants.DATA_PATH + inputFileArray[i];
      }
    }
    inputFilenames = ArgumentsHelper.buildValues(inputFileArray);
    String[] outputFileArray = ArgumentsHelper.getValues(outputFilenames);
    for (int i = 0; i < outputFileArray.length; ++i) {
      if (!outputFileArray[i].startsWith("/") && outputFileArray[i].charAt(1) != ':') {
        outputFileArray[i] = Constants.RESULT_PATH + outputFileArray[i];
      }
    }
    outputFilenames = ArgumentsHelper.buildValues(outputFileArray);

    Class algorithm = Algorithms.getAlgorithm(algorithmName);
    Method method = algorithm.getMethod("main", String[].class);
    String[] args = new String[]{inputFilenames, outputFilenames, parameters};
    method.invoke(null, (Object) args);
    List<ServerTable> results = new ArrayList<>();
    for (String outputFilename : outputFileArray) {
      try {
        IDataSource dataSource = new CsvDataSource(outputFilename);
        results.add(new ServerTable(dataSource.read()));
      } catch (IOException e) {
        results.add(null);
      }
    }
    return results;
  }
}
